/**
 * 
 */
package com.tma.basicfragment.music;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;

import android.util.Xml;

/**
 * @author tqthe
 * 
 */
public class SongParser {
    // We don't use namespaces
    private static final String NAMESPACE = null;

    public List<Song> parse(InputStream in) throws XmlPullParserException, IOException {
        try {
            XmlPullParser parser = Xml.newPullParser();
            parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false);
            parser.setInput(in, null);
            parser.nextTag();
            return readMusic(parser);
        } finally {
            in.close();
        }
    }

    /**
     * Parse the content of the root tag
     * 
     * @param parser
     * @return
     * @throws XmlPullParserException
     * @throws IOException
     */
    public List<Song> readMusic(XmlPullParser parser) throws XmlPullParserException, IOException {
        List<Song> entries = new ArrayList<Song>();

        parser.require(XmlPullParser.START_TAG, NAMESPACE, X.MUSIC);
        while (parser.next() != XmlPullParser.END_TAG) {
            if (parser.getEventType() != XmlPullParser.START_TAG) {
                continue;
            }
            String name = parser.getName();
            // Starts by looking for the "song" tag
            if (name.equals(X.SONG)) {
                entries.add(readSong(parser));
            } else {
                skip(parser);
            }
        }
        return entries;
    }

    /**
     * Parse the content of the "song" tag
     * 
     * @param parser
     * @return the {@link Song} object
     * @throws XmlPullParserException
     * @throws IOException
     */
    private Song readSong(XmlPullParser parser) throws XmlPullParserException,
            IOException {
        parser.require(XmlPullParser.START_TAG, NAMESPACE, X.SONG);

        String id = null;
        String title = null;
        String artist = null;
        String duration = null;
        String thumbUrl = null;

        while (parser.next() != XmlPullParser.END_TAG) {
            if (parser.getEventType() != XmlPullParser.START_TAG) {
                continue;
            }
            String name = parser.getName();
            if (name.equals(X.ID)) {
                id = readId(parser);
            } else if (name.equals(X.TITLE)) {
                title = readTitle(parser);
            } else if (name.equals(X.ARTIST)) {
                artist = readArtist(parser);
            } else if (name.equals(X.DURATION)) {
                duration = readDuration(parser);
            } else if (name.equals(X.THUMB_URL)) {
                thumbUrl = readThumbUrl(parser);
            } else {
                skip(parser);
            }
        }
        Song song = new Song();
        song.setId(id);
        song.setTitle(title);
        song.setArtist(artist);
        song.setDuration(duration);
        song.setThumbUrl(thumbUrl);

        return song;
    }

    private String readThumbUrl(XmlPullParser parser) throws IOException,
            XmlPullParserException {
        parser.require(XmlPullParser.START_TAG, NAMESPACE, X.THUMB_URL);
        String id = readText(parser);
        parser.require(XmlPullParser.END_TAG, NAMESPACE, X.THUMB_URL);
        return id;
    }

    private String readDuration(XmlPullParser parser) throws IOException,
            XmlPullParserException {
        parser.require(XmlPullParser.START_TAG, NAMESPACE, X.DURATION);
        String id = readText(parser);
        parser.require(XmlPullParser.END_TAG, NAMESPACE, X.DURATION);
        return id;
    }

    private String readArtist(XmlPullParser parser) throws IOException,
            XmlPullParserException {
        parser.require(XmlPullParser.START_TAG, NAMESPACE, X.ARTIST);
        String id = readText(parser);
        parser.require(XmlPullParser.END_TAG, NAMESPACE, X.ARTIST);
        return id;
    }

    private String readTitle(XmlPullParser parser) throws IOException,
            XmlPullParserException {
        parser.require(XmlPullParser.START_TAG, NAMESPACE, X.TITLE);
        String id = readText(parser);
        parser.require(XmlPullParser.END_TAG, NAMESPACE, X.TITLE);
        return id;
    }

    private String readId(XmlPullParser parser) throws IOException,
            XmlPullParserException {
        parser.require(XmlPullParser.START_TAG, NAMESPACE, X.ID);
        String id = readText(parser);
        parser.require(XmlPullParser.END_TAG, NAMESPACE, X.ID);
        return id;
    }

    /**
     * Extract the text value
     * 
     * @param parser
     * @return the text value
     * @throws IOException
     * @throws XmlPullParserException
     */
    private String readText(XmlPullParser parser) throws IOException,
            XmlPullParserException {
        String result = "";
        if (parser.next() == XmlPullParser.TEXT) {
            result = parser.getText();
            parser.nextTag();
        }
        return result;
    }

    /**
     * Tell the parser to skip the TAG we are not interested in
     * 
     * @param parser
     *            the XML parser
     * @throws XmlPullParserException
     * @throws IOException
     */
    private void skip(XmlPullParser parser) throws IOException,
            XmlPullParserException {
        if (parser.getEventType() != XmlPullParser.START_TAG) {
            throw new IllegalStateException();
        }
        int depth = 1;
        while (depth != 0) {
            switch (parser.next()) {
            case XmlPullParser.END_TAG:
                depth--;
                break;
            case XmlPullParser.START_TAG:
                depth++;
                break;
            }
        }
    }
}
